#!/bin/sh

. /usr/share/common

gpiodir=/sys/class/gpio

unexport=0

show_help() {
	echo "Usage: $0 <command with params>
Commands:
	export <pin>		Export <pin> from kernel space
	unexport <pin>		Release <pin> back to the kernel space
	input <pin>		Set <pin> as input
	output <pin>		Set <pin> as output
	set <pin> <1|0>		Set <pin> output state to HIGH or LOW
	toggle <pin>		Toggle <pin> output state HIGH/LOW
	read <pin>		Read values of <pin>
	claim <pin>		Claim <pin> to the kernel
	info <pin>		Get information about the <pin>
	list			Show claimed pins via debugfs
Legacy:
	high <pin>		Set <pin1> output state to HIGH
	low <pin>		Set <pin1> output state to LOW
	clear <pin>		Set pin1 output state to LOW
" >&2
	exit 1
}

list_pins() {
	grep -q /sys/kernel/debug /proc/mounts || mount -t debugfs none /sys/kernel/debug
	cat /sys/kernel/debug/gpio
}

claim_pin() {
	export_pin
	echo $pin > /proc/gpio_claim/gpio
}

export_pin() {
	[ -d $gpiodir/gpio$pin ] && return
	echo $pin > $gpiodir/export
}

unexport_pin() {
	[ -d "$gpiodir/gpio$pin" ] || return
	echo $pin > $gpiodir/unexport
}

set_direction() {
	export_pin
	echo $1 > $gpiodir/gpio$pin/direction
}

set_value() {
	set_direction "out"
	echo $1 > $gpiodir/gpio$pin/value
}

toggle_value() {
	if [ "$(get_value)" -eq 0 ]; then
		set_value 1
	else
		set_value 0
	fi
}

get_pin_info() {
	if [ ! -d "$gpiodir/gpio$pin" ]; then
		export_pin
		unexport=1
	fi

	printf "PIN: %d\nACT: %d\nDIR: %s\nVAL: %d\n" \
		$pin \
		$(cat "$gpiodir/gpio$pin/active_low") \
		$(cat "$gpiodir/gpio$pin/direction") \
		$(cat "$gpiodir/gpio$pin/value")

	[ "0$unexport" -eq 1 ] && unexport_pin $pin
}

get_direction() {
	export_pin $pin
	cat $gpiodir/gpio$1/direction
}

get_value() {
	if [ ! -d "$gpiodir/gpio$pin" ]; then
		export_pin $pin
		unexport=1
	fi
	[ -f $gpiodir/gpio$pin/value ] && cat $gpiodir/gpio$pin/value
	[ "0$unexport" -eq 1 ] && unexport_pin "$pin"
}

if [ -n "$2" ]; then
	pin=$(echo $2 | sed s/[^0-9]//g)
	[ -z "$pin" ] && die "PIN $pin IS NOT SET"
else
	[ "list" != "$1" ] && show_help
fi

case "$1" in
	export | catch)
		export_pin ;;
	unexport | release)
		unexport_pin ;;
	input)
		set_direction "in" ;;
	output)
		set_direction "out" ;;
	set)
		set_value ${3:-1} ;;
	toggle)
		toggle_value ;;
	get | read | value)
		get_value ;;
	claim)
		claim_pin ;;
	info)
		get_pin_info ;;
	list)
		list_pins ;;
	clear)
		set_value 0 ;;
	high)
		set_value 1 ;;
	low)
		set_value 0 ;;
	*)
		show_help
		;;
esac

exit 0
